package impl

import (
	"github.com/RaymondCode/simple-demo/entity/po"
	"github.com/RaymondCode/simple-demo/repository"
	"gorm.io/gorm"
	"sync"
)

type User struct {
}

func (u User) Insert(tx *gorm.DB, isTx bool, user *po.User) (int, error) {
	var db1 *gorm.DB
	if isTx {
		db1 = tx
	} else {
		db1 = db
	}
	err := db1.Omit("id", "create_time", "update_time").Create(user).Error
	return (*user).ID, err
}

func (u User) QueryById(userId int) (*po.User, error) {
	db1 := db
	user := po.User{}
	err := db1.Where("id = ?", userId).Find(&user).Error
	return &user, err
}

func (u User) QueryBatchByIds(userIds *[]int) (*[]po.User, error) {
	db1 := db
	userList := make([]po.User, len(*userIds))
	err := db1.Where("id IN ?", *userIds).Find(&userList).Error
	return &userList, err
}

func (u User) QueryByCondition(user *po.User) (*[]po.User, error) {
	db1 := db
	var err error
	var users []po.User
	if user.ID != 0 {
		db1 = db1.Where("id = ?", user.ID)
	}
	if user.Name != "" {
		db1 = db1.Where("name = ?", user.Name)
	}
	err = db1.Find(&users).Error
	return &users, err
}

func (u User) QueryFollows(userId int) (*[]po.User, error) {
	var users = make([]po.User, 0)
	err := db.Raw("SELECT u.* FROM user u, relation r WHERE r.`follower_id` = ? AND u.`id` = r.`follow_id` ORDER BY r.`update_time` DESC", userId).Scan(&users).Error
	if err != nil {
		return nil, err
	}
	return &users, nil
}

func (u User) QueryFans(userId int) (*[]po.User, error) {
	var users = make([]po.User, 0)
	err := db.Raw("SELECT u.* FROM user u, relation r WHERE r.`follow_id` = ? AND u.`id` = r.`follower_id` ORDER BY r.`update_time` DESC", userId).Scan(&users).Error
	if err != nil {
		return nil, err
	}
	return &users, nil
}

func (u User) ChangeFollowCount(userId, difference int, tx *gorm.DB, isTx bool) error {
	var db1 *gorm.DB
	if isTx {
		db1 = tx
	} else {
		db1 = db
	}
	return db1.Model(&po.User{EntityModel: po.EntityModel{ID: userId}}).UpdateColumn("follow_count", gorm.Expr("follow_count + ?", difference)).Error
}

func (u User) ChangeFansCount(userId, difference int, tx *gorm.DB, isTx bool) error {
	var db1 *gorm.DB
	if isTx {
		db1 = tx
	} else {
		db1 = db
	}
	return db1.Model(&po.User{EntityModel: po.EntityModel{ID: userId}}).UpdateColumn("follower_count", gorm.Expr("follower_count + ?", difference)).Error
}

var (
	user     repository.User
	userOnce sync.Once
)

func NewUserDaoInstance() repository.User {
	userOnce.Do(func() {
		user = User{}
	})
	return user
}
